activiti和设计模式(4)

此次行文是从一个定义好的流程定义开始梳理,然后到流程启动,生成一个流程实例,提交第一个任务,任务完成,实例完成,实例完结。学习其中的设计模式,学习框架的设计的理念。

  1. 首先是找到流程的定义:
ProcessDefinition def = repositoryService.createProcessDefinitionQuery().processDefinitionId(
workFlowId).processDefinitionTenantId(orgId).singleResult();

有一个需要注意的问题,这种情况下查找的流程定义,ProcessDefinition没有进行解析彻底,只是数据库字段的映射。

  1. 启动流程实例:
 ProcessInstance ins = runtimeService
 .startProcessInstanceById(workFlowId, formId,variablesObject);

进入命令行:StartProcessInstanceCmd,返回的是一个ProcessInstance,具体的代码是:

public ProcessInstance execute(CommandContext commandContext) {
// 找到部署管理器DeploymentManager
  DeploymentManager deploymentManager = commandContext
    .getProcessEngineConfiguration()//说明①
    .getDeploymentManager();

  // Find the process definition
  ProcessDefinitionEntity processDefinition = null;
  if (processDefinitionId != null) {
    processDefinition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);//说明②
  }
  // .......
  //这个地方省略了依靠其他参变量寻找processDefiniton的代码

  // Do not start process a process instance if the process definition is suspended
  if (deploymentManager.isProcessDefinitionSuspended(processDefinition.getId())) {
    throw new ActivitiException("Cannot start process instance. Process definition "
            + processDefinition.getName() + " (id = " + processDefinition.getId() + ") is suspended");
  }

  // Start the process instance
  ExecutionEntity processInstance = processDefinition.createProcessInstance(businessKey);//说明③

  // now set the variables passed into the start command
  initializeVariables(processInstance);//说明④

  // now set processInstance name
  if (processInstanceName != null) {
    processInstance.setName(processInstanceName);
    commandContext.getHistoryManager().recordProcessInstanceNameChange(processInstance.getId(), processInstanceName);
  }

  processInstance.start();//说明⑤

  return processInstance;
}

说明①:CommandContext,以及processEngineConfiguration 都是单例的模式,只不过从代码上面看,和一般的单例模式不太一样,找不到private的构造方法。

说明②: 通过部署管理器寻找流程定义的过程:

org.activiti.engine.impl.persistence.deploy.DeploymentManager.
findDeployedProcessDefinitionById(String)

首先是到缓存中查找,如果缓存中没有,再到数据库中查找,这个缓存的大小,可以在引擎的配置文件中配置:

<property name="processDefinitionCacheLimit" value="10" />

通过数据库查找的流程定义依然是没有完全解析的,具体的全部的解析的过程在什么地方呢?

public ProcessDefinitionEntity resolveProcessDefinition(ProcessDefinitionEntity processDefinition) {
    String processDefinitionId = processDefinition.getId();
    String deploymentId = processDefinition.getDeploymentId();
    processDefinition = processDefinitionCache.get(processDefinitionId);
    if (processDefinition==null) {
      DeploymentEntity deployment = Context
        .getCommandContext()
        .getDeploymentEntityManager()
        .findDeploymentById(deploymentId);//在这个地方拿到具体的流程定义文件,resource红有值了。
      deployment.setNew(false);
      deploy(deployment, null);//具体的解析发生在这个过程中,activitis填充了解析的内容
      processDefinition = processDefinitionCache.get(processDefinitionId);

      if (processDefinition==null) {
        throw new ActivitiException("deployment '"+deploymentId+"' didn't put process definition '"+processDefinitionId+"' in the cache");
      }
    }
    return processDefinition;
  }

说明③:activiti中没有ProcessInstanceEntity,有的只是ExecutionEntity。创建ExecutionEntity的时候,把历史数据全部的创建,并且插入了数据库中。

另外还有流程实例创建的事件广播出去,这个使用的是观察者模式,这个模式在activiti中可谓是到处都是,主要用于事件的通知,订阅之类的。

// 实例数据创建
 Context.getCommandContext().getHistoryManager()
      .recordProcessInstanceStart(processInstance);

      // 事件广播
      if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
        Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
                ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, processInstance));
    }

说明④:关于流程实例中的变量Variables,需要单独拿出来说明一下。

说明⑤:进入状态机的设计模式

Powered by andiHappy and Theme by AndiHappy